#!/usr/bin/perl -w # for syntax highlighting

use gri_secmgr qw(get_cookie_value redirect_header);
use gri_user_alert_config;
use gri_database;
use MIME::Base64;
use Fcntl ':flock';
use File::Temp qw(tempfile mktemp);

sub mm_form_docrepos_search_process {
my $db_dir=$::GRI_FRONTEND->get_global_directory("database");
my $DB=new gri_database("$db_dir/gri.db");

	my $user=get_cookie_value(name=>"gri_dbm_intranet");
	$user =~ s/\s+.*//;
	my $s="";
	$s="Content-type: text/html\n\n";

	# search = search string
	# search_titles = on [of docs]
	# search_contents = on [of docs]
	# search_reports = on [of report contents]
	# search_maxage = days [maximum upload/mod time of files to search]
	
	# if search_contents == 0 the search is synchronous ... otherwise 
	# we use background processing and pulling until the process completes.

	# If we do not have a pid parameter this is the first time the 
	# search has been done, so we look for local results and spawn a
	# child to perform deep searching if necessary.

	if(!exists($::PARAM{ppid})) {
		my ($temp_fd,$file)=tempfile(DIR=>"/var/tmp");
		my ($lock_fd,$lockfile)=tempfile(DIR=>"/var/tmp", SUFFIX=>".lock");
		my ($statusfile)=mktemp("/var/tmp/search.status.XXXXXXXXX");
		# We firstly get a documentation list to scan ...
		my $db_dir=$::GRI_FRONTEND->get_global_directory("database");
		my $DB=new gri_database("$db_dir/gri.db");
		my ($rc,$ref)=$DB->get_document_list(user => $user);
		# search_type == MW
		# search = search string
		my $search_type=$::PARAM{search_type};
		if(exists($::PARAM{case_sensitive}) && defined($::PARAM{case_sensitive})) {
			$search_type=substr($search_type,1);
		}

		# If doing a full deep search then set up environment and trigger the
		# process ... and then issue request to refresh page...
		{
			my $pid=fork();
			if(!defined($pid)) {
				$s.="Error: Unable to fork process - aborting search :(";
				return $s;
			}
			if($pid>0) {
				# parent, so we trigger a results refresh and exit ...
				# Generate a link to refresh stuff ...

				my $url_prefix=$::GRI_FRONTEND->get_url_prefix();
				my $l="$url_prefix$::ENV{SCRIPT_NAME}";
				my $hex_lockfile=string_to_hex($lockfile);
				my $hex_file=string_to_hex($file);
				my $hex_statusfile=string_to_hex($statusfile);
				$l.="/form_docrepos_search_process?file=$hex_file,statusfile=$hex_statusfile,lockfile=$hex_lockfile,ppid=$pid";
				print STDERR "l=$l\n";
				redirect_header(path => $l);
				exit;
			} else {
				close(STDIN);
				close(STDOUT);
				# close(STDERR);
				# child - so run the search after setting up
				# environment and then exit ... so parent knows when the
				# search has been completed.
				if(exists($::PARAM{search_titles})) {
					$::ENV{GRI_SEARCH_DESCRIPTIONS}=1;
				} else {
					$::ENV{GRI_SEARCH_DESCRIPTIONS}=0;
				}
				if(exists($::PARAM{search_contents})) {
					$::ENV{GRI_SEARCH_CONTENTS}=1;
				} else {
					$::ENV{GRI_SEARCH_CONTENTS}=0;
				}
				$::ENV{GRI_SEARCH_STATUSFILE}=$statusfile;
				if(exists($::PARAM{search_maxage})) {
					$::PARAM{search_maxage}=90 if int($::PARAM{search_maxage})<=0;
					$::ENV{GRI_SEARCH_MAXAGE}=int($::PARAM{search_maxage});
				} else {
					$::ENV{GRI_SEARCH_MAXAGE}=9999;
				}
				if(exists($::PARAM{search_report_names})) {
					$::ENV{GRI_SEARCH_REPORT_NAMES}=1;
				} else {
					$::ENV{GRI_SEARCH_REPORT_NAMES}=0;
				}
				if(exists($::PARAM{search_reports})) {
					$::ENV{GRI_SEARCH_REPORTS}=1;
				} else {
					$::ENV{GRI_SEARCH_REPORTS}=0;
				}
				$::ENV{GRI_SEARCH_USER}=$user;
				$::ENV{GRI_SEARCH_HOME}=dirname($::ENV{SCRIPT_FILENAME});
				$::ENV{GRI_SEARCH_DBFILES}=$db_dir;
				$::ENV{GRI_SEARCH_SEARCHFOR}=$search_type . "|" . $::PARAM{search};
				$::ENV{GRI_SEARCH_RESULTSFILE}=$file;
				$::ENV{GRI_SEARCH_LOCKFILE}=$lockfile;
				my $cmd="cd " . dirname($::ENV{SCRIPT_FILENAME}) . "; bin/gri_searcher";
				print STDERR "export GRI_CONFIG=$::ENV{GRI_CONFIG}\n";
				print STDERR "export GRI_SEARCH_USER=$::ENV{GRI_SEARCH_USER}\n";
				print STDERR "export GRI_SEARCH_HOME=$::ENV{GRI_SEARCH_HOME}\n";
				print STDERR "export GRI_SEARCH_DBFILES=$::ENV{GRI_SEARCH_DBFILES}\n";
				print STDERR "export GRI_SEARCH_SEARCHFOR=$::ENV{GRI_SEARCH_SEARCHFOR}\n";
				print STDERR "export GRI_SEARCH_STATUSFILE=$::ENV{GRI_SEARCH_STATUSFILE}\n";
				print STDERR "export GRI_SEARCH_RESULTSFILE=$::ENV{GRI_SEARCH_RESULTSFILE}\n";
				print STDERR "export GRI_SEARCH_LOCKFILE=$::ENV{GRI_SEARCH_LOCKFILE}\n";
				print STDERR "export GRI_SEARCH_CONTENTS=$::ENV{GRI_SEARCH_CONTENTS}\n";
				print STDERR "export GRI_SEARCH_REPORTS=$::ENV{GRI_SEARCH_REPORTS}\n";
				print STDERR "export GRI_SEARCH_REPORT_NAMES=$::ENV{GRI_SEARCH_REPORT_NAMES}\n";
				print STDERR "export GRI_SEARCH_MAXAGE=$::ENV{GRI_SEARCH_MAXAGE}\n";
				print STDERR "export GRI_SEARCH_DESCRIPTIONS=$::ENV{GRI_SEARCH_DESCRIPTIONS}\n";
				print STDERR "cmd is $cmd\n";
				system($cmd);
				exit;
			}
		}
	}
	# Check if the process is still running, and if it is then we need
	# to trigger a refresh, otherwise no more refreshes...

	my $pid=$::PARAM{ppid};
	my $file=hex_to_string($::PARAM{file});
	my $lockfile=hex_to_string($::PARAM{lockfile});
	my $statusfile=hex_to_string($::PARAM{statusfile});
	my $refresh=2;
	if(! -f $lockfile) {
		$refresh=0;
	}

	# If refresh then dump out a suitable header
	my $css;
	my $username=undef;
	if(!defined($css)) {
		my $v=get_cookie_value(name=>"gri_dbm_intranet");
		if(defined($v)) {
			$v=~ s/\s+.*//;
			$username=$v;
		}
		if(defined($username) && $username ne "public") {
			my $users_dir=$::GRI_FRONTEND->get_global_directory("users");
			if(-f "$users_dir/$username-prefs.xml") {
				my $xx=new gri_userprefs("$users_dir/$username-prefs.xml");
				if($xx) {
					my ($desc,$val)=$xx->get_pref_value("gri_stylesheet");
					if(defined($val)) {
						$css="/stylesheet-$val.css";
					}
				}
			}
		}
	}
	if(!defined($css)) {
		$css=$::ENV{CSS} if exists($::ENV{CSS});
		$css=$::ENV{GRI_STYLE_SHEET} if exists($::ENV{GRI_STYLE_SHEET});
		$css="/StyleGuide.css" if !defined($css);
	}
	load_macro("mm_header");
	if($refresh) {
		$s.="<HTML><HEAD><TITLE>Search Results [In progress]</TITLE>\n";
		$s.="<link rel=\"stylesheet\" type=\"text/css\" href=\"$css\"/>\n";
		$s.="<META http-equiv=\"refresh\" content=\"2\"></HEAD>\n";
		$s.=mm_header();
	} else {
		$s.="<HTML><HEAD><TITLE>Search Results</TITLE>\n";
		$s.="<link rel=\"stylesheet\" type=\"text/css\" href=\"$css\"/>\n";
		$s.="</HEAD>\n";
		$s.=mm_header();
		$s.="<br><h2>Search Results</h2><br>\n";
	}

	# Load in the details of the search ...

	my $sfd;
	open($sfd,$file);
	if(! defined($sfd)) {
		$s.="<BODY><font class=stdtext>Searching underway ... please wait.</font></BODY></HTML>\n";
		return $s;
	}
	my @results=();
	my ($l1,$l2,$l3,$l4,$l5,$l6,$l7);
	while(1) {
		local $SIG{__WARN__}=sub { 1; };
		my $type="doc";
		$l1=<$sfd>;
		$l2=<$sfd>;
		$l3=<$sfd>;
		$l4=<$sfd>;
		$l5=<$sfd>;
		$l6=<$sfd>;
		$l7="";
		if($l1 =~ /^REPNAME:/) {
			$type="rep";
			$l7=<$sfd>;
		}
		last if !defined($l6);
		last if !length($l6);

		chomp($l1);
		chomp($l2);
		chomp($l3);
		chomp($l4);
		chomp($l5);
		chomp($l6);
		chomp($l7);
		if($type eq "doc") {
			my @F1=split(/\s+/,$l1);
			$l2 =~ s/^ONAME: //;
			my @F3=split(/\s+/,$l3);
			my @F4=split(/\s+/,$l4);
			my @F5=split(/\s+/,$l5);
			my @F6=split(/\s+/,$l6);

			push @results,[$type,$F1[1],$l2,$F3[1],$F4[1],$F5[1],$F6[1]];
		} else {
			$l1 =~ s/^REPNAME:\s+//;
			$l2 =~ s/^PORTAL:\s+//;
			$l3 =~ s/^MODTIME:\s+//;
			$l4 =~ s/^DESC:\s+//; $l4=decode_base64($l4);
			$l5 =~ s/^SCORE:\s+//;
			$l6 =~ s/^MATCH:\s+//;
			$l7 =~ s/^MATCHTYPE:\s+//;
			push @results,[$type,$l1,$l2,$l3,$l4,$l5,$l6,$l7];
		}

	}
	close($sfd);
	# We have some results, so get a sort order by score
	if(! @results) {
		if($refresh==0) {
			$s.="<br><h2>Search Results</h2><br>\n";
			$s.="<BODY><font class=stdtext>No results found for the search specified - use the Back button to refine search.</font></BODY></HTML>";
			unlink($::GRI_FRONTEND->get_tmp_content_dir() . "/gri_search.$pid");
			return $s;
		}
		$s.="<BODY>\n";
		my $stat_string="No results returned as yet - still searching.";
		if(-f $statusfile && -s $statusfile) {
			my $stat_fd;
			open($stat_fd,$statusfile);
			if(defined($stat_fd)) {
				my $xx=<$stat_fd>;
				$stat_string=$xx if length($xx);
				close($stat_fd);
			}
		}
		$s.="<br><h2>Search Progression Status</h2><br>\n";
		$s.="<font class=stdtext>$stat_string</font>";
		$s.="</BODY></HTML>\n";
		return $s;
	}
	my $biggest_match=0;
	my @new_results=sort {my $at=$a->[0]; my $bt=$b->[0]; my ($a_sc,$b_sc);
		if($at eq "doc") {$a_sc=$a->[4]} else {$a_sc=$a->[5];}
		if($bt eq "doc") {$b_sc=$b->[4]} else {$b_sc=$b->[5];}
		$biggest_match=$a_sc if $a_sc > $biggest_match;
		$biggest_match=$b_sc if $b_sc > $biggest_match;
		$b_sc <=> $a_sc;
	} @results;

	$biggest_match="$biggest_match.0";
	# print STDERR "Biggest match=$biggest_match\n";
	$s.="<BODY>\n";
	for  my $crow (@new_results) {
		my $type=$crow->[0];
		if($type eq "doc") {
			$s.="<table class=gri_container cols=2>";
			$s.="<tr id=gri_even class=gri_row><td class=gri_cell-header width=15%>Document</td><td class=gri_cell>$crow->[2]</td></tr>\n";
			my $sc_perc=$crow->[4];
			if($biggest_match!=0) {
				$sc_perc=int($sc/$biggest_match*100.0);
			}
			$s.="<tr id=gri_odd class=gri_row><td class=gri_cell-header>Match</td><td class=gri_cell>" . decode_base64($crow->[5]) . " [$sc_perc\% - $crow->[6]]</td></tr>\n";

			$s.="<tr id=gri_even class=gri_row><td class=gri_cell-header>Actions</td><td class=gri_cell>" . link_to_str("stdlink","View","docrepos_view_document","document_sha1=$crow->[3],lname=$crow->[1]") . "</td></tr>\n";
			$s.="</table><br>\n";
		} else {
			my $sc_perc=$crow->[5];
			$s.="<table class=gri_container cols=2>";
			$s.="<tr id=gri_even class=gri_row><td class=gri_cell-header width=15%>Report</td><td class=gri_cell>" . $crow->[1] . "</td></tr>\n";
			$s.="<tr id=gri_odd class=gri_row><td class=gri_cell-header>Portal</td><td class=gri-cell>$crow->[2]</td></tr>\n";
			$s.="<tr id=gri_even class=gri_row><td class=gri_cell-header>Report date</td><td class=gri_cell>$crow->[3]</td></tr>\n";
			$s.="<tr id=gri_odd class=gri_row><td class=gri_cell-header>Match</td><td class=gri_cell>" . decode_base64($crow->[6]) . " [$sc_perc\% - $crow->[7]]</td></tr>\n";
			my $mtime=$crow->[3]; $mtime =~ s/\/.*//;
			$s.="<tr class=gri_row><td class=gri_cell-header>Actions></td><td class=gri_cell>" . link_to_str("stdlink","View","portal_file_view","repname=" . string_to_hex($crow->[1]) . ",portal=" . string_to_hex($crow->[2]) . ",repmtime=" . string_to_hex($mtime)) . "</td></tr>\n";
			$s.="</table><br>\n";
		}
	}
	$s.="</BODY></HTML>\n";
	if($refresh==0) {
		unlink($file);
	}
	return $s;
}

1;

